/* 该文件对应的解释：/home/ubuntu/project-practice/Imitate_Muduo_Server/Any.cpp */
#include <iostream>
#include <typeinfo>
#include <cassert>


class Any{
private:
    Any& Swap(Any& other){
        std::swap(_content, other._content);
        return *this;
    }

public:
    //注意：构造来说，本身是没有的！

    //默认构造
    Any():_content(nullptr){}

    //拷贝构造
    //每一个Any容器都有一个Clone接口
    //但是，很可能other的指向存储的指针是空的，就没办法调用了，所以需要判断一下！
    Any(const Any& other):_content(other._content ? _content = other._content->Clone() : nullptr){}
   
    //通过输入类型的变量来进行构造
    template<class T>
    Any(const T& val):_content(new PlaceHolder<T>(val)){}

    //析构
    ~Any(){delete _content;}

    //赋值重载 
    //返回引用是为了方便连续赋值
    Any& operator=(const Any& other){
        //原本的那个存储的会给到临时对象，出函数作用域后自动析构
        Any(other).Swap(*this);
        return *this;
    }

    //拷贝赋值
    template<class T>
    Any& operator=(const T& val){
        //原本的那个存储的会给到临时对象，出函数作用域后自动析构
        Any(val).Swap(*this);
        return *this;
    }

    //我们还希望能够通过一个接口，获得当前Any容器所存储的内容
    template<class T>
    T* Get(){
        //必须要保证获取的时候，用户输入的类型必须和获取的是一致的！
        assert(_content->Type() == typeid(T));
        return &(static_cast<PlaceHolder<T>*>(_content)->_val);
    }

private:

//Holder是一个父类，它不负责存储任意的数据！它只声明一些基本的虚函数
    class Holder{
    public:
        Holder(){}
        virtual ~Holder() {}
        //可能会有需要拷贝一个存储任意类型数据的容器指针
        virtual Holder* Clone() = 0;
        //有可能需要进行类型的检查，万一外界获取内容的时候，传入的类型和存储的不一样？
        virtual const std::type_info& Type() = 0;
    private:
    };

//PlaceHolder继承Holder父类，它是用来进行存储任意数据的一个类！
    template<class T>
    class PlaceHolder : public Holder{
    public:
        PlaceHolder(){}

        PlaceHolder(const T& val):_val(val){}

        ~PlaceHolder(){}

        virtual Holder* Clone() override{return new PlaceHolder<T>(_val);}

        //detail：return val
        //这里的返回值必须是 const std::type_info& 要不然报错了
        virtual const std::type_info& Type() override{return typeid(T);}

    public:
        T _val;
    };

//Any类内存储一个父类指针，指向的是子类PlaceHolder
//到时候存储，操作，都是通过这个指针进行操作的！
    Holder* _content;
};

class Test{
public:
    Test(){std::cout << "Test()" << std::endl;}
    Test(const Test& t){std::cout << "Test(const Test& t)" << std::endl;}
    ~Test(){std::cout << "~Test()" << std::endl;}
};

int main(){
    /* Any a;
    a = 10;
    int* pa = a.Get<int>();
    std::cout << *pa << std::endl;

    Any b(std::string("daaasad"));
    std::string* ps = b.Get<std::string>();
    std::cout << *ps << std::endl;

    a = b;
    ps = a.Get<std::string>();
    std::cout << *ps << std::endl; */



    {
        Any a;
        Test t;
        a = t;
    }

    

    return 0;
}